home *** CD-ROM | disk | FTP | other *** search
Wrap
// Sky dome shader code // Note that some of the sky dome code comes from the book "Shader X2: Shader Programming Tips & Tricks with DirectX 9" ed. by Engel // Code from the article: "Advanced Sky Dome Rendering" by Marco Spoerl and Kurt Pelzer // License opposite CD at end of book: "You may use the source code, techniques, and example programs // in your own commercial or private applications unless otherwise noted by additional usage agreements // as found on the CD." //----------------------------------------------------------------------------- texture SunTexture; texture MoonTexture; texture MoonBumpMap; texture CloudsCubeMap; texture StarsTexture; //----------------------------------------------------------------------------- float4x4 WorldViewProj; float4x4 SunTexTransform; float4x4 MoonTexTransform; float4 sunlight_normal; float4 sunlight_color; float4 sun_to_moon; float4 fog_color; float star_show_amt; // figure these out static float4 KrConsts = { 1.0f, 0.5f, 0.6f, 0.0f }; // Raleigh scattering? static float4 KmConsts = { 0.02f, 0.8f, 1.6f, 0.0f }; // Mie scattering? //----------------------------------------------------------------------------- // Texture sampling attributes sampler SunTextureSampler = sampler_state //!FIX does it matter if sampler2D or just sampler? { Texture = <SunTexture>; MinFilter = Linear; MagFilter = Linear; // MipFilter = Point; // what should this be? AddressU = Clamp; AddressV = Clamp; // AddressW = Clamp; // want this? }; sampler MoonTextureSampler = sampler_state //!FIX does it matter if sampler2D or just sampler? { Texture = <MoonTexture>; MinFilter = Linear; MagFilter = Linear; // MipFilter = Point; // what should this be? AddressU = Clamp; AddressV = Clamp; // AddressW = Clamp; // want this? }; samplerCUBE CloudsCubeMapSampler = sampler_state { Texture = <CloudsCubeMap>; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; }; sampler StarsSampler = sampler_state { Texture = <StarsTexture>; MinFilter = Linear; MagFilter = Linear; MipFilter = Linear; }; //----------------------------------------------------------------------------- // Passed in to vertex shader struct vertexInput { float4 position : POSITION; float3 normal : NORMAL; // float4 color : COLOR0; float2 texCoord : TEXCOORD0; }; struct vertexOutput { float4 position : POSITION; float4 color : COLOR0; float4 belowHorizon : COLOR1; float4 sunTexCoord : TEXCOORD0; float4 moonTexCoord : TEXCOORD1; float3 eyeVector : TEXCOORD2; float2 starsTexCoord : TEXCOORD3; }; struct vertexOutputPlain { float4 position : POSITION; float4 color : COLOR0; float4 belowHorizon : COLOR1; float4 sunTexCoord : TEXCOORD0; float4 moonTexCoord : TEXCOORD1; }; //----------------------------------------------------------------------------- // vertexOutputPlain VS_TransformPlain( vertexInput IN ) { vertexOutputPlain OUT; // Transform position to clip space OUT.position = mul(IN.position, WorldViewProj); // don't need to set w to 1, done automatically // The radius of the sky dome is 10000. So you're dividing the position on the sphere, the height, // by the radius of the sphere, which is the sine of the angle from the viewer's point of view. // If the point is on the horizon, the angle is zero, and sin(0) == 0/10000. // If the point is straight up, the angle is 90 degrees, and sin(90 deg) == 1 == 10000/10000. // So IN.position.z/10000.0 will vary from -1 to 1, and step will vary from 0 to 2. // We only care about positive values of IN.position.z, 'cause if it's negative, the // color will be set to the fog color. See below. float step = IN.position.z/10000.0f + 1.0f; // z coord of dome as if dome radius was 50. z-axis is perpendicular to game terrain. float cos_angle_from_sun = dot(IN.normal, sunlight_normal); // both should be already normalized // calculate fr (molecule scattering) float fr = (cos_angle_from_sun > 0.0f) ? cos_angle_from_sun * cos_angle_from_sun : 0.0f; fr = fr * 0.75f + 0.75f; // calculate fm (aerosol scattering) // a cosine shouldn't ever be > 1, but I'll use >= just in case of floating point inprecision float fm = (abs(cos_angle_from_sun) >= 1.0f) ? 1.75f : 0.75f; // KR color of the molocules float3 kr = KrConsts * fr; // KM color of the aerosols float3 km = KmConsts * fm + kr; //km *= 2000.0f; // pre-multiplied KrConsts & KmConsts by 2000 instead // scale by steps km *= step; // output color OUT.color.rgb = (IN.position.z <= 0) ? fog_color : km * sunlight_color ; // show fog color if point below horizon OUT.color.a = 1.0f; // alpha float4 sunTexCoord = mul( IN.position, SunTexTransform); OUT.sunTexCoord = sunTexCoord; OUT.moonTexCoord = mul(IN.position, MoonTexTransform); OUT.belowHorizon = (IN.position.z <= 0) ? 0 : 1; // if this part of sky dome is below the horizon, don't show sun, moon, etc. return OUT; } //----------------------------------------------------------------------------- vertexOutput VS_Transform( vertexInput IN ) { vertexOutput OUT; // Transform position to clip space OUT.position = mul(IN.position, WorldViewProj); // don't need to set w to 1, done automatically // The radius of the sky dome is 10000. So you're dividing the position on the sphere, the height, // by the radius of the sphere, which is the sine of the angle from the viewer's point of view. // If the point is on the horizon, the angle is zero, and sin(0) == 0/10000. // If the point is straight up, the angle is 90 degrees, and sin(90 deg) == 1 == 10000/10000. // So IN.position.z/10000.0 will vary from -1 to 1, and step will vary from 0 to 2. // We only care about positive values of IN.position.z, 'cause if it's negative, the // color will be set to the fog color. See below. float step = IN.position.z/10000.0f + 1.0f;//IN.texCoord.x * IN.texCoord.x; // z coord of dome as if dome radius was 50. z-axis is perpendicular to game terrain. float cos_angle_from_sun = dot(IN.normal, sunlight_normal); // both should be already normalized // calculate fr (molecule scattering) float fr = (cos_angle_from_sun > 0.0f) ? cos_angle_from_sun * cos_angle_from_sun : 0.0f; fr = fr * 0.75f + 0.75f; // calculate fm (aerosol scattering) // a cosine shouldn't ever be > 1, but I'll use >= just in case of floating point inprecision float fm = (abs(cos_angle_from_sun) >= 1.0f) ? 1.75f : 0.75f; // KR color of the molocules float3 kr = KrConsts * fr; // KM color of the aerosols float3 km = KmConsts * fm + kr; //km *= 2000.0f; // pre-multiplied KrConsts & KmConsts by 2000 instead // scale by steps km *= step; // output color OUT.color.rgb = (IN.position.z <= 0) ? fog_color : km * sunlight_color ; // show fog color if point below horizon OUT.color.a = 1.0f; // alpha float4 sunTexCoord = mul( IN.position, SunTexTransform); OUT.sunTexCoord = sunTexCoord; OUT.moonTexCoord = mul(IN.position, MoonTexTransform); // clouds OUT.eyeVector = IN.position.xzy; //swap z & y (in Empire Earth code, Z points up, not Y) OUT.belowHorizon = (IN.position.z <= 0) ? 0 : 1; // if this part of sky dome is below the horizon, don't show sun, moon, etc. OUT.starsTexCoord = IN.texCoord; return OUT; } //----------------------------------- // Simple pixel shader. float4 PS_ColorPlain( vertexOutput IN ): COLOR { float belowHorizon = IN.belowHorizon; // if this part of sky dome is below the horizon, don't show sun, moon, etc. float4 sun = tex2D(SunTextureSampler, IN.sunTexCoord) ; float4 moon = tex2D(MoonTextureSampler, IN.moonTexCoord); float4 color = sun * (1 - IN.color) + IN.color + moon ; // where sun texture is white, show white. If sun texture is black, show original color. color = saturate(color); color = belowHorizon * color + (1.0 - belowHorizon) *IN.color; // if below horizon, don't show sun, moon // color = saturate(color); return color; } //----------------------------------- // Simple pixel shader. float4 PS_Color( vertexOutput IN ): COLOR { float4 color = IN.color; float belowHorizon = IN.belowHorizon; // if this part of sky dome is below the horizon, don't show sun, moon, etc. float4 sun = tex2D(SunTextureSampler, IN.sunTexCoord) ; float4 moon = tex2D(MoonTextureSampler, IN.moonTexCoord); float4 stars = tex2D(StarsSampler, IN.starsTexCoord); // what about alpha? const float star_fade_in_limit = 0.5f; star_show_amt = saturate(star_show_amt * star_fade_in_limit); // makes compiler happy - next instruction requires fewer instructions color = (1.0 - star_show_amt) * color + star_show_amt * stars; // HLSL lerp function not allowed in PS 1.1 ?! ASM lrp is! color = saturate(color); // makes compiler happy, can generate a complement on next line color = sun * (1 - color) + color + moon ; // where sun texture is white, show white. If sun texture is black, show original color. //color = saturate(color); float4 clouds = texCUBE(CloudsCubeMapSampler , IN.eyeVector); //clouds = saturate(clouds); // makes compiler happy // Composite the cloud environment map color = (clouds.a * clouds) + ((1.0 - clouds.a) * color); color = belowHorizon * color + (1.0 - belowHorizon) *IN.color; // if below horizon, don't show sun, moon, stars // color = saturate(color); return color; } //----------------------------------------------------------------------------- technique RenderPlainSky { pass P0 { VertexShader = compile vs_1_1 VS_TransformPlain(); PixelShader = compile ps_1_1 PS_ColorPlain(); CullMode = None; Texture[0] = <SunTexture>; Texture[1] = <MoonTexture>; TexCoordIndex[0] = 0; TexCoordIndex[1] = 1; TextureTransformFlags[0] = Projected; TextureTransformFlags[1] = Projected; //FillMode = Wireframe; FogEnable = False; ZEnable = True; ZWriteEnable = False; } } technique RenderSky { pass P0 { VertexShader = compile vs_1_1 VS_Transform(); PixelShader = compile ps_1_2 PS_Color(); CullMode = None; Texture[0] = <SunTexture>; Texture[1] = <MoonTexture>; Texture[2] = <CloudsCubeMap>; Texture[3] = <StarsTexture>; TexCoordIndex[0] = 0; TexCoordIndex[1] = 1; TexCoordIndex[2] = 2; TexCoordIndex[3] = 3; TextureTransformFlags[0] = Projected; TextureTransformFlags[1] = Projected; TextureTransformFlags[2] = Disable; TextureTransformFlags[3] = Disable; //FillMode = Wireframe; FogEnable = False; ZEnable = True; ZWriteEnable = False; } }